home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / sptmbr16.lha / low.lisp < prev    next >
Lisp/Scheme  |  1992-12-21  |  15KB  |  446 lines

  1. ;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
  2. ;;;
  3. ;;; *************************************************************************
  4. ;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
  5. ;;; All rights reserved.
  6. ;;;
  7. ;;; Use and copying of this software and preparation of derivative works
  8. ;;; based upon this software are permitted.  Any distribution of this
  9. ;;; software or derivative works must comply with all applicable United
  10. ;;; States export control laws.
  11. ;;; 
  12. ;;; This software is made available AS IS, and Xerox Corporation makes no
  13. ;;; warranty about the software, its performance or its conformity to any
  14. ;;; specification.
  15. ;;; 
  16. ;;; Any person obtaining a copy of this software is requested to send their
  17. ;;; name and post office or electronic mail address to:
  18. ;;;   CommonLoops Coordinator
  19. ;;;   Xerox PARC
  20. ;;;   3333 Coyote Hill Rd.
  21. ;;;   Palo Alto, CA 94304
  22. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  23. ;;;
  24. ;;; Suggestions, comments and requests for improvements are also welcome.
  25. ;;; *************************************************************************
  26. ;;;
  27. ;;; This file contains portable versions of low-level functions and macros
  28. ;;; which are ripe for implementation specific customization.  None of the
  29. ;;; code in this file *has* to be customized for a particular Common Lisp
  30. ;;; implementation. Moreover, in some implementations it may not make any
  31. ;;; sense to customize some of this code.
  32. ;;;
  33. ;;; But, experience suggests that MOST Common Lisp implementors will want
  34. ;;; to customize some of the code in this file to make PCL run better in
  35. ;;; their implementation.  The code in this file has been separated and
  36. ;;; heavily commented to make that easier.
  37. ;;;
  38. ;;; Implementation-specific version of this file already exist for:
  39. ;;; 
  40. ;;;    Symbolics Genera family     genera-low.lisp
  41. ;;;    Lucid Lisp                  lucid-low.lisp
  42. ;;;    Xerox 1100 family           xerox-low.lisp
  43. ;;;    ExCL (Franz)                excl-low.lisp
  44. ;;;    Kyoto Common Lisp           kcl-low.lisp
  45. ;;;    Vaxlisp                     vaxl-low.lisp
  46. ;;;    CMU Lisp                    cmu-low.lisp
  47. ;;;    H.P. Common Lisp            hp-low.lisp
  48. ;;;    Golden Common Lisp          gold-low.lisp
  49. ;;;    Ti Explorer                 ti-low.lisp
  50. ;;;    
  51. ;;;
  52. ;;; These implementation-specific files are loaded after this file.  Because
  53. ;;; none of the macros defined by this file are used in functions defined by
  54. ;;; this file the implementation-specific files can just contain the parts of
  55. ;;; this file they want to change.  They don't have to copy this whole file
  56. ;;; and then change the parts they want.
  57. ;;;
  58. ;;; If you make changes or improvements to these files, or if you need some
  59. ;;; low-level part of PCL re-modularized to make it more portable to your
  60. ;;; system please send mail to CommonLoops.pa@Xerox.com.
  61. ;;;
  62. ;;; Thanks.
  63. ;;; 
  64.  
  65. (in-package :pcl)
  66.  
  67. (eval-when (compile load eval)
  68. (defvar *optimize-speed* '(optimize (speed 3) (safety 0)))
  69. )
  70.  
  71. (defmacro %svref (vector index)
  72.   `(locally (declare #.*optimize-speed*
  73.              (inline svref))
  74.         (svref (the simple-vector ,vector) (the fixnum ,index))))
  75.  
  76. (defsetf %svref %set-svref)
  77.  
  78. (defmacro %set-svref (vector index new-value)
  79.   `(locally (declare #.*optimize-speed*
  80.              (inline svref))
  81.      (setf (svref (the simple-vector ,vector) (the fixnum ,index))
  82.        ,new-value)))
  83.  
  84.  
  85. ;;;
  86. ;;; without-interrupts
  87. ;;; 
  88. ;;; OK, Common Lisp doesn't have this and for good reason.  But For all of
  89. ;;; the Common Lisp's that PCL runs on today, there is a meaningful way to
  90. ;;; implement this.  WHAT I MEAN IS:
  91. ;;;
  92. ;;; I want the body to be evaluated in such a way that no other code that is
  93. ;;; running PCL can be run during that evaluation.  I agree that the body
  94. ;;; won't take *long* to evaluate.  That is to say that I will only use
  95. ;;; without interrupts around relatively small computations.
  96. ;;;
  97. ;;; INTERRUPTS-ON should turn interrupts back on if they were on.
  98. ;;; INTERRUPTS-OFF should turn interrupts back off.
  99. ;;; These are only valid inside the body of WITHOUT-INTERRUPTS.
  100. ;;;
  101. ;;; OK?
  102. ;;;
  103. (defmacro without-interrupts (&body body)
  104.   `(macrolet ((interrupts-on () ())
  105.           (interrupts-off () ()))
  106.      (progn ,.body)))
  107.  
  108.  
  109. ;;;
  110. ;;;  Very Low-Level representation of instances with meta-class standard-class.
  111. ;;;
  112. #-new-kcl-wrapper
  113. (progn
  114. (defstruct (std-instance (:predicate std-instance-p)
  115.              (:conc-name %std-instance-)
  116.              (:constructor %%allocate-instance--class ())
  117.              (:print-function print-std-instance))
  118.   (wrapper nil)
  119.   (slots nil))
  120.  
  121. (defmacro %instance-ref (slots index)
  122.   `(%svref ,slots ,index))
  123.  
  124. (defmacro instance-ref (slots index)
  125.   `(svref ,slots ,index))
  126. )
  127.  
  128. #+new-kcl-wrapper
  129. (progn
  130. (defvar *init-vector* (make-array 40 :fill-pointer 1 :adjustable t 
  131.                   :initial-element nil))
  132.  
  133. (defun get-init-list (i)
  134.   (declare (fixnum i)(special *slot-unbound*))
  135.   (loop (when (< i (fill-pointer *init-vector*))
  136.       (return (aref *init-vector* i)))
  137.     (vector-push-extend 
  138.      (cons *slot-unbound*
  139.            (aref *init-vector* (1- (fill-pointer *init-vector*))))
  140.      *init-vector*)))
  141.  
  142. (defmacro %std-instance-wrapper (instance)
  143.   `(structure-def ,instance))
  144.  
  145. (defmacro %std-instance-slots (instance)
  146.   instance)
  147.  
  148. (defmacro std-instance-p (x)
  149.   `(structurep ,x))
  150. )
  151.  
  152. (defmacro std-instance-wrapper (x) `(%std-instance-wrapper ,x))
  153. (defmacro std-instance-slots   (x) `(%std-instance-slots ,x))
  154.  
  155. (defmacro get-wrapper (inst)
  156.   `(cond ((std-instance-p ,inst) (std-instance-wrapper ,inst))
  157.      ((fsc-instance-p ,inst) (fsc-instance-wrapper ,inst))
  158.      (t (error "What kind of instance is this?"))))
  159.  
  160. (defmacro get-instance-wrapper-or-nil (inst)
  161.   `(cond ((std-instance-p ,inst) (std-instance-wrapper ,inst))
  162.      ((fsc-instance-p ,inst) (fsc-instance-wrapper ,inst))))
  163.  
  164. (defmacro get-slots (inst)
  165.   `(cond ((std-instance-p ,inst) (std-instance-slots ,inst))
  166.      ((fsc-instance-p ,inst) (fsc-instance-slots ,inst))
  167.      (t (error "What kind of instance is this?"))))
  168.  
  169. (defmacro get-slots-or-nil (inst)
  170.   `(cond ((std-instance-p ,inst) (std-instance-slots ,inst))
  171.      ((fsc-instance-p ,inst) (fsc-instance-slots ,inst))))
  172.  
  173. (defun print-std-instance (instance stream depth) ;A temporary definition used
  174.   (declare (ignore depth))                  ;for debugging the bootstrap
  175.   (printing-random-thing (instance stream)        ;code of PCL (See high.lisp).
  176.     (let ((class (class-of instance)))
  177.       (if (or (eq class (find-class 'standard-class nil))
  178.           (eq class (find-class 'funcallable-standard-class nil))
  179.           (eq class (find-class 'built-in-class nil)))
  180.       (format stream "~a ~a" (early-class-name class)
  181.           (early-class-name instance))
  182.       (format stream "~a" (early-class-name class))))))
  183.  
  184. ;;;
  185. ;;; This is the value that we stick into a slot to tell us that it is unbound.
  186. ;;; It may seem gross, but for performance reasons, we make this an interned
  187. ;;; symbol.  That means that the fast check to see if a slot is unbound is to
  188. ;;; say (EQ <val> '..SLOT-UNBOUND..).  That is considerably faster than looking
  189. ;;; at the value of a special variable.  Be careful, there are places in the
  190. ;;; code which actually use ..slot-unbound.. rather than this variable.  So
  191. ;;; much for modularity
  192. ;;; 
  193. (defvar *slot-unbound* '..slot-unbound..)
  194.  
  195. (defmacro %allocate-static-slot-storage--class (no-of-slots)
  196.   #+new-kcl-wrapper (declare (ignore no-of-slots))
  197.   #-new-kcl-wrapper
  198.   `(make-array ,no-of-slots :initial-element *slot-unbound*)
  199.   #+new-kcl-wrapper
  200.   (error "don't call this"))
  201.  
  202. (defmacro std-instance-class (instance)
  203.   `(wrapper-class* (std-instance-wrapper ,instance)))
  204.  
  205.  
  206.   ;;   
  207. ;;;;;; FUNCTION-ARGLIST
  208.   ;;
  209. ;;; Given something which is functionp, function-arglist should return the
  210. ;;; argument list for it.  PCL does not count on having this available, but
  211. ;;; MAKE-SPECIALIZABLE works much better if it is available.  Versions of
  212. ;;; function-arglist for each specific port of pcl should be put in the
  213. ;;; appropriate xxx-low file. This is what it should look like:
  214. ;(defun function-arglist (function)
  215. ;  (<system-dependent-arglist-function> function))
  216.  
  217. (defun function-pretty-arglist (function)
  218.   (declare (ignore function))
  219.   ())
  220.  
  221. (defsetf function-pretty-arglist set-function-pretty-arglist)
  222.  
  223. (defun set-function-pretty-arglist (function new-value)
  224.   (declare (ignore function))
  225.   new-value)
  226.  
  227. ;;;
  228. ;;; set-function-name
  229. ;;; When given a function should give this function the name <new-name>.
  230. ;;; Note that <new-name> is sometimes a list.  Some lisps get the upset
  231. ;;; in the tummy when they start thinking about functions which have
  232. ;;; lists as names.  To deal with that there is set-function-name-intern
  233. ;;; which takes a list spec for a function name and turns it into a symbol
  234. ;;; if need be.
  235. ;;;
  236. ;;; When given a funcallable instance, set-function-name MUST side-effect
  237. ;;; that FIN to give it the name.  When given any other kind of function
  238. ;;; set-function-name is allowed to return new function which is the 'same'
  239. ;;; except that it has the name.
  240. ;;;
  241. ;;; In all cases, set-function-name must return the new (or same) function.
  242. ;;; 
  243. (defun set-function-name (function new-name)
  244.   (declare (notinline set-function-name-1 intern-function-name))
  245.   (set-function-name-1 function
  246.                (intern-function-name new-name)
  247.                new-name))
  248.  
  249. (defun set-function-name-1 (function new-name uninterned-name)
  250.   (declare (ignore new-name uninterned-name))
  251.   function)
  252.  
  253. (defun intern-function-name (name)
  254.   (cond ((symbolp name) name)
  255.     ((listp name)
  256.      (intern (let ((*package* *the-pcl-package*)
  257.                (*print-case* :upcase)
  258.                (*print-pretty* nil)
  259.                (*print-gensym* 't))
  260.            (format nil "~S" name))
  261.          *the-pcl-package*))))
  262.  
  263.  
  264. ;;;
  265. ;;; COMPILE-LAMBDA
  266. ;;;
  267. ;;; This is like the Common Lisp function COMPILE.  In fact, that is what
  268. ;;; it ends up calling.  The difference is that it deals with things like
  269. ;;; watching out for recursive calls to the compiler or not calling the
  270. ;;; compiler in certain cases or allowing the compiler not to be present.
  271. ;;;
  272. ;;; This starts out with several variables and support functions which 
  273. ;;; should be conditionalized for any new port of PCL.  Note that these
  274. ;;; default to reasonable values, many new ports won't need to look at
  275. ;;; these values at all.
  276. ;;;
  277. ;;; *COMPILER-PRESENT-P*        NIL means the compiler is not loaded
  278. ;;;
  279. ;;; *COMPILER-SPEED*            one of :FAST :MEDIUM or :SLOW
  280. ;;;
  281. ;;; *COMPILER-REENTRANT-P*      T   ==> OK to call compiler recursively
  282. ;;;                             NIL ==> not OK
  283. ;;;
  284. ;;; function IN-THE-COMPILER-P  returns T if in the compiler, NIL otherwise
  285. ;;;                             This is not called if *compiler-reentrant-p*
  286. ;;;                             is T, so it only needs to be implemented for
  287. ;;;                             ports which have non-reentrant compilers.
  288. ;;;
  289. ;;;
  290. (defvar *compiler-present-p* t)
  291.  
  292. (defvar *compiler-speed*
  293.     #+(or KCL IBCL GCLisp CMU) :slow
  294.     #-(or KCL IBCL GCLisp CMU) :fast)
  295.  
  296. (defvar *compiler-reentrant-p*
  297.     #+(and (not XKCL) (or KCL IBCL)) nil
  298.     #-(and (not XKCL) (or KCL IBCL)) t)
  299.  
  300. (defun in-the-compiler-p ()
  301.   #+(and (not xkcl) (or KCL IBCL))compiler::*compiler-in-use*
  302.   #+gclisp (typep (eval '(function (lambda ()))) 'lexical-closure)
  303.   )
  304.  
  305. (defvar *compile-lambda-break-p* nil)
  306.  
  307. (defun compile-lambda (lambda &optional (desirability :fast))
  308.   (when *compile-lambda-break-p* (break))
  309.   (cond ((null *compiler-present-p*)
  310.      (compile-lambda-uncompiled lambda))
  311.     ((and (null *compiler-reentrant-p*)
  312.           (in-the-compiler-p))
  313.      (compile-lambda-deferred lambda))
  314.     ((eq desirability :fast)
  315.      (compile nil lambda))
  316.     ((and (eq desirability :medium)
  317.           (member *compiler-speed* '(:fast :medium)))
  318.      (compile nil lambda))
  319.     ((and (eq desirability :slow)
  320.           (eq *compiler-speed* ':fast))
  321.      (compile nil lambda))
  322.     (t
  323.      (compile-lambda-uncompiled lambda))))
  324.  
  325. (defun compile-lambda-uncompiled (uncompiled)
  326.   #'(lambda (&rest args) (apply (coerce uncompiled 'function) args)))
  327.  
  328. (defun compile-lambda-deferred (uncompiled)
  329.   (let ((function (coerce uncompiled 'function))
  330.     (compiled nil))
  331.     (declare (type (or function null) compiled))
  332.     #'(lambda (&rest args)
  333.     (if compiled
  334.         (apply compiled args)
  335.         (if (in-the-compiler-p)
  336.         (apply function args)
  337.         (progn (setq compiled (compile nil uncompiled))
  338.                (apply compiled args)))))))
  339.  
  340. (defmacro precompile-random-code-segments (&optional system)
  341.   `(progn
  342.      (eval-when (compile)
  343.        (update-dispatch-dfuns)
  344.        (compile-iis-functions nil))
  345.      (precompile-function-generators ,system)
  346.      (precompile-dfun-constructors ,system)
  347.      (precompile-iis-functions ,system)
  348.      (eval-when (load)
  349.        (compile-iis-functions t))))
  350.  
  351.  
  352.  
  353. (defun record-definition (type spec &rest args)
  354.   (declare (ignore type spec args))
  355.   ())
  356.  
  357. (defun doctor-dfun-for-the-debugger (gf dfun) (declare (ignore gf)) dfun)
  358.  
  359. ;; From braid.lisp
  360. #-new-kcl-wrapper
  361. (defmacro built-in-or-structure-wrapper (x)
  362.   (once-only (x)
  363.     (if (structure-functions-exist-p) ; otherwise structurep is too slow for this
  364.     `(if (structurep ,x)
  365.          (wrapper-for-structure ,x)
  366.          (if (symbolp ,x)
  367.          (if ,x *the-wrapper-of-symbol* *the-wrapper-of-null*)
  368.          (built-in-wrapper-of ,x)))
  369.     `(or (and (symbolp ,x)
  370.           (if ,x *the-wrapper-of-symbol* *the-wrapper-of-null*))
  371.          (built-in-or-structure-wrapper1 ,x)))))
  372.  
  373.  
  374. ;Low level functions for structures
  375.  
  376.  
  377. ;Functions on arbitrary objects
  378.  
  379. (defvar *structure-table* (make-hash-table :test 'eq))
  380.  
  381. (defun declare-structure (name included-name slot-description-list)
  382.   (setf (gethash name *structure-table*)
  383.     (cons included-name slot-description-list)))
  384.  
  385. (unless (fboundp 'structure-functions-exist-p)
  386.   (setf (symbol-function 'structure-functions-exist-p) 
  387.     #'(lambda () nil)))
  388.  
  389. (defun default-structurep (x)
  390.   (structure-type-p (type-of x)))
  391.  
  392. (defun default-structure-instance-p (x)
  393.   (let ((type (type-of x)))
  394.     (and (not (eq type 'std-instance))
  395.      (structure-type-p type))))
  396.  
  397. (defun default-structure-type (x)
  398.   (type-of x))
  399.  
  400. (unless (fboundp 'structurep)
  401.   (setf (symbol-function 'structurep) #'default-structurep))
  402.  
  403. ; excludes std-instance
  404. (unless (fboundp 'structure-instance-p)
  405.   (setf (symbol-function 'structure-instance-p) #'default-structure-instance-p))
  406.  
  407. ; returns a symbol
  408. (unless (fboundp 'structure-type)
  409.   (setf (symbol-function 'structure-type) #'default-structure-type))
  410.  
  411.  
  412. ;Functions on symbols naming structures
  413.  
  414. ; Excludes structures types created with the :type option
  415. (defun structure-type-p (symbol)
  416.   (not (null (gethash symbol *structure-table*))))
  417.  
  418. (defun structure-type-included-type-name (symbol)
  419.   (car (gethash symbol *structure-table*)))
  420.  
  421. ; direct slots only
  422. ; The results of this function are used only by the functions below.
  423. (defun structure-type-slot-description-list (symbol)
  424.   (cdr (gethash symbol *structure-table*)))
  425.  
  426.  
  427. ;Functions on slot-descriptions (returned by the function above)
  428.  
  429. ;returns a symbol
  430. (defun structure-slotd-name (structure-slot-description)
  431.   (first structure-slot-description))
  432.  
  433. ;returns a symbol
  434. (defun structure-slotd-accessor-symbol (structure-slot-description)
  435.   (second structure-slot-description))
  436.  
  437. ;returns a symbol or a list or nil
  438. (defun structure-slotd-writer-function (structure-slot-description)
  439.   (third structure-slot-description))
  440.  
  441. (defun structure-slotd-type (structure-slot-description)
  442.   (fourth structure-slot-description))
  443.  
  444. (defun structure-slotd-init-form (structure-slot-description)
  445.   (fifth structure-slot-description))
  446.